//
//  VNCView.m
//  vnsea
//
//  Created by Chris Reed on 9/5/07.
//  Copyright 2007 __MyCompanyName__. All rights reserved.
// Modified by: Glenn Kreisel

#import "VNCView.h"
#import "VNCPopupView.h"
#import "VnseaApp.h"
#import <CoreGraphics/CoreGraphics.h>
#import <UIKit/UIKit.h>
#import <UIKit/UITextView.h>
#import <UIKit/UITouchDiagnosticsLayer.h>
#import <UIKit/UINavBarButton.h>
#import <UIKit/UIView-Gestures.h>
#import <UIKit/UIKeyboardImpl.h>
#import <UIKit/UIView-Deprecated.h>
#import <UIKit/UIKeyboardLayoutQWERTY.h>
#import <UIKit/UIKeyboardLayoutQWERTYLandscape.h>
#import <UIKit/UITextView.h>
#import <UIKit/UITextTraits.h>
#import <GraphicsServices/GraphicsServices.h>
#import "RectangleList.h"
#import "QueuedEvent.h"
#import "VNCPreferences.h"
#import <IOKit/IOKitLib.h>

//! Height of the controls bar view.
#define kControlsBarHeight (48.0f)

//! Height of buttons in the controls bar.
#define kControlsBarButtonHeight (32.0f)

#define kKeyboardButtonWidth (40.0f)
#define kExitButtonWidth (28.0f)
#define kRightMouseButtonWidth (28.0f)
#define kModifierKeyButtonWidth (32.0f)
#define kRemoteKeyButtonWidth (58.0f)
#define kButtonSpacing (4.0f)

#define kModifierKeyImageWidth (21.0f)
#define kModifierKeyImageHeight (21.0f)

// There's got to be a better way to do this, but for now this is just fine.
// Thanks to the MobileTerminal team for this trick.
@implementation UIKeyboardImpl (DisableFeatures)

- (BOOL)autoCapitalizationPreference
{
	return NO;
}

- (BOOL)autoCorrectionPreference
{
	return NO;
}

@end

@implementation VNCView

- (void)acceleratedInX:(float)xx Y:(float)yy Z:(float)zz
{
	[_filter acceleratedInX:xx Y:yy Z:zz];
}

- (void)remoteButtonPressed:(id)sender
{
	[_remoteScroller setScrollingEnabled:NO];
	[self stopSendingRemoteControlKeys];

	RemoteButton *rb = [_remoteButtons getButtonByControl: sender];
	if (rb != nil)
	{
		NSLog(@"pressed from %@, with keyalias %@ and keyreleasealias %@", sender, [rb getKeyAlias], [rb getKeyReleaseAlias]);
		if ([rb getKeyReleaseAlias] == nil && _isMediaConnected)
			[self startSendingRemoteControlKeys: rb];
		else
			[self sendRemoteControlKey: [rb getKeyAlias]];
	}
}

- (void)remoteButtonReleased:(id)sender
{
	[_remoteScroller setScrollingEnabled:YES];
	NSLog(@"unpressed from %@", sender);
	[self stopSendingRemoteControlKeys];

	RemoteButton *rb = [_remoteButtons getButtonByControl: sender];
	if (rb != nil)
	{
		if ([rb getKeyReleaseAlias] != nil)
			[self sendRemoteControlKey: [rb getKeyReleaseAlias]];
	}
}

- (void)startSendingRemoteControlKeys:(RemoteButton*)rb
{
	[self sendRemoteControlKey: [rb getKeyAlias]];
	[self stopSendingRemoteControlKeys];
	_keySendTimer = [[NSTimer scheduledTimerWithTimeInterval:.5 target:self selector:@selector(handleKeySendTimer:) userInfo:(id)rb repeats:NO] retain];
//	NSLog(@"started first timer %@", rowcol);
}

- (void)handleKeySendTimer:(NSTimer *)timer
{
	RemoteButton *rb= (RemoteButton*)[timer userInfo];
	[self stopSendingRemoteControlKeys];
	_keySendTimer = [[NSTimer scheduledTimerWithTimeInterval:.2 target:self selector:@selector(handleKeySendTimerRepeater:) userInfo:(id)rb repeats:YES] retain];
//	NSLog(@"infinite timer %@ started", rowcol);
}

- (void)handleKeySendTimerRepeater:(NSTimer *)timer
{
	RemoteButton *rb= (RemoteButton*)[timer userInfo];
	NSLog(@"infinite timer %@", [rb getKeyAlias]);
	[self sendRemoteControlKey: [rb getKeyAlias]];
}

- (void)stopSendingRemoteControlKeys
{
//	NSLog(@"stopped!");
	if (_keySendTimer)
	{
		[_keySendTimer invalidate];
		[_keySendTimer release];
		_keySendTimer = nil;
	}
}

- (void)sendRemoteControlKey:(NSString *)keyalias
{
	[_connection sendRemoteControlKey: keyalias];
	[self cancelGlowingModifiers];
}

- (void)sendFunctionKeys:(int)num
{
	[_connection sendFunctionKey: (unsigned)num];
}

- (void)sendESCKey:(id)sender
{	
	[_connection sendEscapeKey];
}

- (void)sendTabKey:(id)sender
{	
	[_connection sendTabKey];
}

- (void)sendCtrlAltDel:(id)sender
{
	[_connection sendCtrlAltDel:nil];
}

- (void)sendFullRefresh:(id)sender
{
	[_connection sendFullScreenRefresh];
}

// I can never remember this relationship for some reason:
// The frame rectangle defines the view's location and size in the superview using the superview’s coordinate system. The bounds rectangle defines the interior coordinate system that is used when drawing the contents of the view, including the origin and scaling.
- (id)initWithFrame:(CGRect)frame
{
	if ([super initWithFrame:frame])
	{
		CGRect subframe = frame;
		subframe.origin = CGPointMake(0, 0);
		subframe.size.height -= kControlsBarHeight;
		
		// Create scroller view.
		_scroller = [[VNCScrollerView alloc] initWithFrame:subframe];
		[_scroller setVNCView: self];
		[_scroller setScrollingEnabled:YES];
		[_scroller setShowScrollerIndicators:YES];
		[_scroller setAdjustForContentSizeChange:NO];
		[_scroller setAllowsRubberBanding:YES];
		[_scroller setAllowsFourWayRubberBanding:YES];
		[_scroller setRubberBand: 50 forEdges:0];
		[_scroller setRubberBand: 50 forEdges:1];
		[_scroller setRubberBand: 50 forEdges:2];
		[_scroller setRubberBand: 50 forEdges:3];
		[_scroller setDelegate:self];
		
		// Create controls bar.
		[self layoutControlsBar];
		
		// Create screen view.
		subframe.origin.y = 0;
		_screenView = [[VNCContentView alloc] initWithFrame:subframe];
		[_screenView setDelegate: [self delegate]];
	
		// Set our background color to black.
		const float kBlackComponents[] = { 0, 0, 0, 1 };
		CGColorSpaceRef rgbSpace = CGColorSpaceCreateDeviceRGB();
		CGColorRef black = CGColorCreate(rgbSpace, kBlackComponents);
		CGColorSpaceRelease(rgbSpace);
		
		[self setOpaque:YES];
		[self setBackgroundColor:black];
				
//		[_scroller setBackgroundColor:GSColorCreateColorWithDeviceRGBA(0,0,1, 0.2)];
//		[self setBackgroundColor:GSColorCreateColorWithDeviceRGBA(1,0,0, 0.2)];

		// Build view hierarchy.
		[self addSubview:_controlsView];
		[_scroller addSubview:_screenView];
		[self addSubview:_scroller];
		
		// Init some instance variables.
		_areControlsVisible = NO;
		_isKeyboardVisible = NO;
		_scaleState = kScaleFitNone;
		_ipodScreenSize = CGSizeMake(frame.size.width, frame.size.height);
	}
	_currentPage = 0;
	_shownControlsOnce = NO;
	return self;
}

//! This method creates the controls bar that appears at the bottom of the display
//! in portrait mode, as well as all of the buttons within it.
- (void)layoutControlsBar
{
	CGRect frame = [self frame];
	// Create control bar, initially just below the bottom of the screen.
	CGRect subframe = CGRectMake(0, frame.size.height, frame.size.width, kControlsBarHeight);
	_controlsView = [[UIGradientBar alloc] initWithFrame:subframe];
	
	[self initControlsBar];
}

- (void)initControlsBar
{
	CGRect frame = [self frame], subframe;
	bool bMacMode = [_connection macMode];
	
	if (_keyboardButton)
	{
		[_keyboardButton removeFromSuperview];
		[_exitButton removeFromSuperview];
		[_shiftButton removeFromSuperview];
		[_commandButton removeFromSuperview];
		[_optionButton removeFromSuperview];
		[_controlButton removeFromSuperview];
		[_helperFunctionButton removeFromSuperview];
		[_rightMouseButton removeFromSuperview];
		[_keyboardButton release];
		[_exitButton release];
		[_shiftButton release];
		[_commandButton release];
		[_optionButton release];
		[_controlButton release];
		[_helperFunctionButton release];
		[_rightMouseButton release];
		_keyboardButton = nil;
		_exitButton = nil;
		_shiftButton = nil;
		_commandButton = nil;
		_optionButton = nil;
		_controlButton = nil;
		_helperFunctionButton = nil;
		_rightMouseButton = nil;
	}

	UIImageView *glowview;
	
	// Create keyboard button.
	subframe = CGRectMake(5, (kControlsBarHeight - kControlsBarButtonHeight) / 2.0f + 1.0f, kKeyboardButtonWidth, kControlsBarButtonHeight);
	_keyboardButton = [[UINavBarButton alloc] initWithImage:[UIImage imageNamed:@"keyboard.png"]];
	[_keyboardButton setFrame:subframe];
	[_keyboardButton setNavBarButtonStyle:0];
	[_keyboardButton setDrawContentsCentered:YES];
	glowview = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"glow.png"]];
	[glowview setAlpha: 0.0f];
	[_keyboardButton addSubview: glowview];
	[_keyboardButton addTarget:self action:@selector(toggleKeyboard:) forEvents:kUIControlEventMouseUpInside];
	
	// Modifier key buttons.
	subframe = CGRectMake(CGRectGetMaxX(subframe) + kButtonSpacing, (kControlsBarHeight - kControlsBarButtonHeight) / 2.0f + 1.0f, kModifierKeyButtonWidth, kControlsBarButtonHeight);
	if (!bMacMode)
		_shiftButton = [[UINavBarButton alloc] initWithTitle:NSLocalizedString(@"Shift Abbreviated", nil)];
	else
		_shiftButton = [[UINavBarButton alloc] initWithImage:[UIImage imageNamed:@"shift_key.png"]];
	[_shiftButton setTitleFont:GSFontCreateWithName("HelveticaBold", 0, 12.0f)];
	[_shiftButton setFrame:subframe];
	[_shiftButton setNavBarButtonStyle:0];
	glowview = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"glow.png"]];
	[glowview setAlpha: 0.0f];
	[_shiftButton addSubview: glowview];
	[_shiftButton setDrawContentsCentered:YES];
	[_shiftButton addTarget:self action:@selector(toggleModifierKey:) forEvents:kUIControlEventMouseUpInside];
	
	subframe.origin.x = CGRectGetMaxX(subframe) + kButtonSpacing;
	if (!bMacMode)
		_controlButton = [[UINavBarButton alloc] initWithTitle:NSLocalizedString(@"Control Abbreviated", nil)];
	else
		_controlButton = [[UINavBarButton alloc] initWithImage:[UIImage imageNamed:@"ctrl_key.png"]];
	[_controlButton setTitleFont:GSFontCreateWithName("HelveticaBold", 0, 12.0f)];
	[_controlButton setFrame:subframe];
	[_controlButton setNavBarButtonStyle:0];
	[_controlButton setDrawContentsCentered:YES];
	glowview = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"glow.png"]];
	[glowview setAlpha: 0.0f];
	[_controlButton addSubview: glowview];
	[_controlButton addTarget:self action:@selector(toggleModifierKey:) forEvents:kUIControlEventMouseUpInside];
	
	subframe.origin.x = CGRectGetMaxX(subframe) + kButtonSpacing;
	if (!bMacMode)
		_commandButton = [[UINavBarButton alloc] initWithTitle:NSLocalizedString(@"Alternate Abbreviated",nil)];
	else
		_commandButton = [[UINavBarButton alloc] initWithImage:[UIImage imageNamed:@"cmd_key.png"]];
	if (!bMacMode)
		[_commandButton setTitleFont:GSFontCreateWithName("HelveticaBold", 0, 12.0f)];
//	NSLog(@"font: %@", [NSString stringWithCString: GSFontGetFamilyName([_commandButton titleFont])]);
//	[_commandButton setTitlePadding:CGSizeMake(0,0)];
	[_commandButton setFrame:subframe];
	[_commandButton setNavBarButtonStyle:0];
	glowview = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"glow.png"]];
	[glowview setAlpha: 0.0f];
	[_commandButton addSubview: glowview];
	[_commandButton setDrawContentsCentered:YES];
	[_commandButton addTarget:self action:@selector(toggleModifierKey:) forEvents:kUIControlEventMouseUpInside];
	
	subframe.origin.x = CGRectGetMaxX(subframe) + kButtonSpacing;
	if (!bMacMode)
		_optionButton = [[UINavBarButton alloc] initWithImage:[UIImage imageNamed:@"win_key.png"]];
//		_optionButton = [[UINavBarButton alloc] initWithTitle:NSLocalizedString(@"Function Abbreviated",nil)];
	else
		_optionButton = [[UINavBarButton alloc] initWithImage:[UIImage imageNamed:@"opt_key.png"]];
	[_optionButton setFrame:subframe];
	[_optionButton setNavBarButtonStyle:0];
	glowview = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"glow.png"]];
	[glowview setAlpha: 0.0f];
	[_optionButton addSubview: glowview];
	[_optionButton setDrawContentsCentered:YES];
	[_optionButton addTarget:self action:@selector(toggleModifierKey:) forEvents:kUIControlEventMouseUpInside];
	
	// Helper Functions "more" button on the status bar
	subframe = CGRectMake(subframe.origin.x + kModifierKeyButtonWidth + kButtonSpacing , (kControlsBarHeight - kControlsBarButtonHeight) / 2.0f + 1.0f, kRemoteKeyButtonWidth, kControlsBarButtonHeight);
	_helperFunctionButton = [[UINavBarButton alloc] initWithTitle:NSLocalizedString(@"Remote Control Abbreviated", nil)];
	[_helperFunctionButton setFrame:subframe];
	[_helperFunctionButton setNavBarButtonStyle:0];
	[_helperFunctionButton setDrawContentsCentered:YES];
	[_helperFunctionButton addTarget:self action:@selector(toggleRemote:) forEvents:kUIControlEventMouseUpInside];

	// Right mouse button.
	subframe = CGRectMake(subframe.origin.x + kRemoteKeyButtonWidth + kButtonSpacing , (kControlsBarHeight - kControlsBarButtonHeight) / 2.0f + 1.0f, kRightMouseButtonWidth, kControlsBarButtonHeight);
//	_rightMouseButton = [[UINavBarButton alloc] initWithImage:[UIImage imageNamed:@"right_mouse.png"]]; //WithTitle:@"W" autosizesToFit:NO];
	_rightMouseButton = [[UINavBarButton alloc] initWithTitle:@"?" autosizesToFit:NO];
	[_rightMouseButton setTitleFont:GSFontCreateWithName("HelveticaBold", 0, 19.0f)];
	[_rightMouseButton setFrame:subframe];
	[_rightMouseButton setNavBarButtonStyle:0];
	[_rightMouseButton setDrawContentsCentered:YES];
	[_rightMouseButton addTarget:self action:@selector(getHelp:) forEvents:kUIControlEventMouseUpInside];
	
	// Terminate connection button.
	subframe = CGRectMake(frame.size.width - kExitButtonWidth - 5, (kControlsBarHeight - kControlsBarButtonHeight) / 2.0f + 1.0f, kExitButtonWidth, kControlsBarButtonHeight);
	_exitButton = [[UINavBarButton alloc] initWithTitle:@"X" autosizesToFit:NO];
	[_exitButton setTitleFont:GSFontCreateWithName("HelveticaBold", 0, 19.0f)];
	[_exitButton setFrame:subframe];
	[_exitButton setNavBarButtonStyle:0];
	[_exitButton setDrawContentsCentered:YES];
	[_exitButton addTarget:self action:@selector(closeConnection:) forEvents:kUIControlEventMouseUpInside];
	
	// Build controls bar view hierarchy.
	[_controlsView addSubview:_keyboardButton];
	[_controlsView addSubview:_exitButton];
	[_controlsView addSubview:_shiftButton];
	[_controlsView addSubview:_commandButton];
	[_controlsView addSubview:_optionButton];
	[_controlsView addSubview:_controlButton];
	[_controlsView addSubview:_helperFunctionButton];
	[_controlsView addSubview:_rightMouseButton];
}

- (void)displayConnectionErrors
{
	NSLog(@"macmode %d", [_connection macMode]);
	if (!_showedTMSerror && [_connection failedToConnectToMediaServer])
	{
		_showedTMSerror = true;
		if ([_connection macMode])
			[self displayError: NSLocalizedString(@"NoMediaServerMacSupport", nil) Title:NSLocalizedString(@"MediaServerFailedToConnectErrorTitle", nil)];
		else
			[self displayError: NSLocalizedString(@"MediaServerFailedToConnectError", nil) Title:NSLocalizedString(@"MediaServerFailedToConnectErrorTitle", nil)];
	}
	
	if ([_connection triedScreenViewWithoutActivating])
		[self displayError: NSLocalizedString(@"NoActivationScreenViewError", nil) Title:NSLocalizedString(@"NoActivationScreenViewErrorTitle", nil)];
}

- (void)displayNoMediaServerError
{
	[self displayError: NSLocalizedString(@"NoMediaServerError", nil) Title: NSLocalizedString(@"NoMediaServerErrorTitle", nil)];
}

- (void)displayError: (NSString*) text Title:(NSString*) title
{
	UIAlertSheet *errorPopup = [[UIAlertSheet alloc ] initWithFrame:CGRectMake(0,0,250,350) ];	
	[errorPopup setTitle:title];
	[errorPopup setDelegate:self];
	[errorPopup setContext:self];
	[errorPopup setDimsBackground:YES];
	[errorPopup addButtonWithTitle:NSLocalizedString(@"OK", nil)];
//	[errorPopup addButtonWithTitle:NSLocalizedString(@"Donate Later", nil)];
//	[errorPopup addButtonWithTitle:NSLocalizedString(@"Tell Me More", nil)];

	[errorPopup _slideSheetOut:YES];
	[errorPopup layoutAnimated:NO];
	[errorPopup setBodyText:text];
	[errorPopup popupAlertAnimated:YES atOffset:0.0];
	[errorPopup setAlpha:1.0f];
}

- (void)dealloc
{
    [super dealloc];
}

- (id)scroller
{
	return _scroller;
}

- (bool)areControlsVisible
{
	return _areControlsVisible;
}

-(void)updateControls
{
	[_delegate setStatusBarShowsProgress: false];

	CGRect frame = [self frame];
	
	if ([self getOrientationState] == kOrientationVertical)
		[_controlsView setFrame:CGRectMake(0, frame.size.height, frame.size.width, kControlsBarHeight)];
	else 
		[_controlsView setFrame:CGRectMake(0, frame.size.height+71, frame.size.width, kControlsBarHeight)];

	[UIView beginAnimations:nil];
	[UIView setAnimationDuration:0];

	frame = [_controlsView frame];
	frame.origin.y -= kControlsBarHeight;
	[_controlsView setFrame:frame];

		
	// This will start the animation.
	[UIView endAnimations];
	
	frame = [self frame];
	frame.size.height -= kControlsBarHeight;
//	[_scroller setFrame: frame];
//	_dbgtxt = [NSString stringWithFormat: @"%f,%f", [self frame].size.height, [self frame].size.width];
}

//! Either hides or shows the controls bar at the bottom of the screen
//! (in portrait orientation). The hiding or showing is animated.
- (void)showControls:(bool)show
{
	if (_areControlsVisible != show && !_shownControlsOnce)
	{
		_shownControlsOnce=YES;
		CGRect frame;
		
		[UIView beginAnimations:nil];
		[UIView setAnimationDuration:0.15f];

		if (_areControlsVisible)
		{
			// Hide the keyboard if it was in view.
			if (_isKeyboardVisible)
			{
				[self toggleKeyboard:nil];
			}
			
			// Hide controls
			frame = [_controlsView frame];
			frame.origin.y = [self frame].size.height;
			[_controlsView setFrame:frame];
			
			frame = [_scroller frame];
			frame.size.height += kControlsBarHeight;
			[_scroller setFrame:frame];
			_ipodScreenSize.height += kControlsBarHeight;
			
			// Hide the keyboard if it was in view.
			if (_isKeyboardVisible)
			{
				[self toggleKeyboard:nil];
			}
		}
		else
		{
		
			// Show controls
			frame = [_controlsView frame];
			frame.origin.y -= kControlsBarHeight;
			[_controlsView setFrame:frame];
			
			frame = [_scroller frame];
			frame.size.height -= kControlsBarHeight;
			[_scroller setFrame:frame];
			_ipodScreenSize.height -= kControlsBarHeight;
		}
		
		// This will start the animation.
		[UIView endAnimations];
		
		_areControlsVisible = show;
	}
}

- (float)orientationDegree
{
	return [_screenView getOrientationDeg];
}

- (void)toggleControls
{
	[self showControls:!_areControlsVisible];
}

- (CGPoint)topLeftVisiblePt
{
	return [_scroller bounds].origin;
}

- (void)changeViewPinnedToPoint:(CGPoint)ptPinned scale:(float)fScale orientation:(UIHardwareOrientation)wOrientationState force:(BOOL)bForce
{
	[_scroller changeViewPinnedToPoint:ptPinned scale:fScale orientation:wOrientationState force:bForce];
}

- (void)setStartupTopLeftPt:(CGPoint)pt
{
	_ptStartupTopLeft = pt;
}

- (void)startTunesStatusTimer
{
	[self stopTunesStatusTimer];
	float interval = isStatusFast ? 0.1 : 1;
//	NSLog(@"starting statustimer %f", interval);
	_tunesStatusTimer = [[NSTimer scheduledTimerWithTimeInterval:interval target:self selector:@selector(getTunesStatus:) userInfo:nil repeats:YES] retain];
}

- (void)stopTunesStatusTimer
{
	if (_tunesStatusTimer)
	{
		[_tunesStatusTimer invalidate];
		[_tunesStatusTimer release];
		_tunesStatusTimer = nil;
	}
}

- (void)getTunesStatus:(NSTimer*)timer
{
	[self sendRemoteControlKey: @"TunesTrackStatus"];
}

- (void)displayStatus:(NSString*)input
{
	NSString *txt = @"";
	float val=-1;
	NSString *timedone = nil, *timeleft = nil;
	NSArray *sections = [input componentsSeparatedByString: @":"];
	NSString *command = (NSString*)[sections objectAtIndex: 0];
	if ([command isEqualToString: @"NoStatus"])
	{
		[self stopTunesStatusTimer];
	}
	if ([command isEqualToString: @"Stopped"])
	{
		txt = (NSString*)[sections objectAtIndex: 0];
		[self stopTunesStatusTimer];
	}
	if ([command isEqualToString: @"Message"])
	{
		txt = (NSString*)[sections objectAtIndex: 1];
		[self stopTunesStatusTimer];
	}
	if ([command isEqualToString: @"TrackStatus"])
	{
		txt = [NSString stringWithFormat: @"%@", (NSString *)[sections objectAtIndex: 1]];
		int secsdone = [(NSString*)[sections objectAtIndex: 2] intValue];
		int secstotal = [(NSString*)[sections objectAtIndex: 3] intValue];
		isStatusFast = [(NSString*)[sections objectAtIndex: 4] isEqualToString: @"Fast"];
	
		int secsleft = secstotal - secsdone;
		val = (float)secsdone / (float)secstotal;
		NSMutableString *secsstring, *minstring;
		int mins;

		secsstring = [NSString stringWithFormat: (secsdone % 60) < 10 ? @"0%d" : @"%d", secsdone % 60];
		mins = secsdone / 60;
		minstring = [NSString stringWithFormat: (mins % 60) < 10 ? @"0%d" : @"%d", mins % 60];
		if (mins < 60)
			timedone = [NSString stringWithFormat: @"%d:%@", mins, secsstring];
		else
			timedone = [NSString stringWithFormat: @"%d:%@:%@", mins / 60, minstring, secsstring];
		
		secsstring = [NSString stringWithFormat: (secsleft % 60) < 10 ? @"0%d" : @"%d", secsleft % 60];
		mins = secsleft / 60;
		minstring = [NSString stringWithFormat: (mins % 60) < 10 ? @"0%d" : @"%d", mins % 60];
		if (mins < 60)
			timeleft = [NSString stringWithFormat: @"-%d:%@", mins, secsstring];
		else
			timeleft = [NSString stringWithFormat: @"-%d:%@:%@", mins / 60, minstring, secsstring];
		
		[self startTunesStatusTimer];
		_lastTrackTotalSecs = secstotal;
	}
	if ([command isEqualToString: @"Volume"])
	{
		if ([(NSString *)[sections objectAtIndex: 1] isEqualToString: @"Mute"])
			txt = @"Volume Muted";
		else
		{
			txt = @"Volume";
			val = [(NSString*)[sections objectAtIndex: 2] floatValue] / 100.0f;
//			timeleft = [NSString stringWithFormat: @"%d%%", [(NSString*)[sections objectAtIndex: 2] intValue]];
		}
		[self stopTunesStatusTimer];
	}

	[self stopStatusFade];
	float oldAlpha = -1;
	if (_statusLabel)
	{
		oldAlpha = [_statusLabel alpha];
		[_statusLabel removeFromSuperview];
		[_statusLabel release];
		
		[_scrubber removeFromSuperview];
		[_scrubber release];

		[_leftLabel removeFromSuperview];
		[_leftLabel release];

		[_rightLabel removeFromSuperview];
		[_rightLabel release];
	}			

	int labelx = 3, labely = 33, labelwidth = 50;
	_leftLabel = [[UITextLabel alloc] initWithFrame:CGRectMake(labelx, labely, labelwidth, 20)];
	if (timedone != nil)
	{
		[_leftLabel setFont:GSFontCreateWithName("Verdana", 0, 14.0f)];
		[_leftLabel setBackgroundColor:GSColorCreateColorWithDeviceRGBA(0,0,0, 0)];
		[_leftLabel setColor:GSColorCreateColorWithDeviceRGBA(1,1,1, 1)];
		[_leftLabel setCentersHorizontally: true];
		[_leftLabel setText: timedone];
		[_leftLabel setAlpha: oldAlpha];
		[_leftLabel sizeToFit];
		[_leftLabel setOrigin: CGPointMake(MAX(0,(67 - [_leftLabel frame].size.width)/2), labely)];
		[_remoteHolder addSubview:_leftLabel];
	}	

	_rightLabel = [[UITextLabel alloc] initWithFrame:CGRectMake([self frame].size.width - labelwidth - labelx, labely, labelwidth, 20)];
	if (timeleft != nil)
	{
		[_rightLabel setFont:GSFontCreateWithName("Verdana", 0, 14.0f)];
		[_rightLabel setBackgroundColor:GSColorCreateColorWithDeviceRGBA(0,0,0, 0)];
		[_rightLabel setColor:GSColorCreateColorWithDeviceRGBA(1,1,1, 1)];
		[_rightLabel setCentersHorizontally: true];
		[_rightLabel setText: timeleft];
		[_rightLabel setAlpha: oldAlpha];
		[_rightLabel sizeToFit];
		[_rightLabel setOrigin: CGPointMake([_remoteHolder frame].size.width - [_rightLabel frame].size.width - labelx - (67 - [_rightLabel frame].size.width)/2, [_rightLabel frame].origin.y)];
		[_remoteHolder addSubview:_rightLabel];
	}


	_statusLabel = [[UITextLabel alloc] initWithFrame:CGRectMake(0, 0, [self frame].size.width, 40)];
	[_statusLabel setFont:GSFontCreateWithName("Verdana", 0, 14.0f)];
	[_statusLabel setBackgroundColor:GSColorCreateColorWithDeviceRGBA(0,0,0, 0.0f)];
//	[_statusLabel setBackgroundColor:GSColorCreateColorWithDeviceRGBA(1,0,0, 0.4f)];
	[_statusLabel setColor:GSColorCreateColorWithDeviceRGBA(1,1,1, 1)];
	[_statusLabel setCentersHorizontally: true];
	[_statusLabel setText: txt];
	[_statusLabel setWrapsText: YES];
	
	int labelwidths = labelx * 2 + [_leftLabel frame].size.width + [_rightLabel frame].size.width;
	int scrubberwidth = [_remoteHolder frame].size.width - labelwidths;
	_scrubber = [[UIScrubberControl alloc] initWithFrame:CGRectMake(0, labely - 2, [_remoteHolder frame].size.width, 0) maxTrackWidth:180 showTimes:NO showKnob:YES];
	if (val >= 0)
	{
		[_scrubber setMinValue:0.0];
		[_scrubber setMaxValue:1.0];
		[_scrubber setValue:val];
		[_scrubber setDuration:1.0];
		[_scrubber setPinTimeToOutsideEdges:YES];
		[_scrubber setShowDuration:YES];
		[_scrubber setDelegate:self];	
		[_scrubber setAlpha: oldAlpha];
		[_scrubber addTarget:self action:@selector(handleSliderDown:) forEvents:kUIControlEventMouseDown];
		[_scrubber addTarget:self action:@selector(handleSliderUp:) forEvents:kUIControlEventMouseUpInside | kUIControlEventMouseUpOutside];
		[_scrubber setBackgroundColor:GSColorCreateColorWithDeviceRGBA(0,0,0, 0.0f)];
//		[_scrubber setBackgroundColor:GSColorCreateColorWithDeviceRGBA(0,1,0, 0.4f)];
		[_remoteHolder addSubview:_scrubber];
	}
	
	if (![command isEqualToString: @"Message"])
	{
		if (_lastStatusCommand)
			[_lastStatusCommand release];
		_lastStatusCommand = command;
		[_lastStatusCommand retain];
	}
//	NSLog(@"prevalpha %.2f", oldAlpha);
	isFadeIn = YES;
	[_statusLabel setAlpha: oldAlpha];
	_statusFadeTimer = [[NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(fade:) userInfo:nil repeats:NO] retain];
	[_remoteHolder addSubview:_statusLabel];
}

-(void) handleSliderDown:(id)etc
{
	NSLog(@"slider down %@", etc);
	[self stopStatusFade];
	[self stopTunesStatusTimer];
}

-(void) handleSliderUp:(id)etc
{
	if ([_lastStatusCommand isEqualToString: @"Volume"])
	{
		int val = [_scrubber value] * 100;
		[self sendRemoteControlKey: [NSString stringWithFormat: @"TunesSetVolume Full %d", val]];
	}
	else if ([_lastStatusCommand isEqualToString: @"TrackStatus"])
	{
		float val = [_scrubber value];
		int seektime = val * _lastTrackTotalSecs;
		[self sendRemoteControlKey: [NSString stringWithFormat: @"TunesSeek Full %d", seektime]];
	}
}

- (void)stopStatusFade
{
	if (_statusFadeTimer)
	{
		[_statusFadeTimer invalidate];
		[_statusFadeTimer release];
		_statusFadeTimer = nil;
	}
}

-(void)fade: (NSTimer *)timer
{
//	NSLog(@"fading %.2f", [_statusLabel alpha]);
	if ((isFadeIn && [_statusLabel alpha] < 0.999f) || (!isFadeIn && [_statusLabel alpha] > 0.001f))
	{
//		NSLog(@"a");
		[_statusLabel setAlpha: [_statusLabel alpha] + (isFadeIn ? 0.01f : -0.01f)];
	}
	if ((isFadeIn && [_statusLabel alpha] < 0.999f) || (!isFadeIn && [_statusLabel alpha] > 0.001f))
	{
//		NSLog(@"b");
		_statusFadeTimer = [[NSTimer scheduledTimerWithTimeInterval:0.005 target:self selector:@selector(fade:) userInfo:nil repeats:NO] retain];
	}
		
	if (isFadeIn && [_statusLabel alpha] > 0.999f)
	{
//		NSLog(@"c");
		isFadeIn = NO;
		_statusFadeTimer = [[NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(fade:) userInfo:nil repeats:NO] retain];
	}
	[_scrubber setAlpha: [_statusLabel alpha]];
	[_leftLabel setAlpha: [_statusLabel alpha]];
	[_rightLabel setAlpha: [_statusLabel alpha]];
	if (!isFadeIn && [_statusLabel alpha]<=0.001f && ![_lastStatusCommand isEqualToString: @"Stopped"] && ![_lastStatusCommand isEqualToString: @"NoStatus"])
	{
		[self startTunesStatusTimer];
	}
}

- (void)dbg: (NSString*)txt
{
	if (_dbgtxtlbl)
	{
		[_dbgtxtlbl removeFromSuperview];
		[_dbgtxtlbl release];
	}			
	_dbgtxtlbl = [[UITextLabel alloc] initWithFrame:CGRectMake(5, 100, 280, 100)];
	[_dbgtxtlbl setFont:GSFontCreateWithName("Verdana", 0, 9.0f)];
//	[_dbgtxtlbl setBackgroundColor:GSColorCreateColorWithDeviceRGBA(0,0,0, 1)];
//	[_dbgtxtlbl setColor:GSColorCreateColorWithDeviceRGBA(1,1,1, 1)];
	[_dbgtxtlbl setCentersHorizontally: true];
	[_dbgtxtlbl setText: txt];
	[_dbgtxtlbl setWrapsText: YES];
//	[_dbgtxtlbl setAlpha: 0.5];
	[self addSubview:_dbgtxtlbl];
}

- (void)toggleRemote: (id)sender
{
	if (!_isRemoteActive)
	{
		if (_isKeyboardVisible)
			[self toggleKeyboard:nil];

	[self addSubview:_remoteHolder];
//		if (_remoteScroller)
//			[_remoteScroller dealloc];
//		[self initRemote];
	}
	else
	{
//		[_pageIndicator removeFromSuperview];
//		[_pageIndicator release];
		[_remoteHolder removeFromSuperview];
	}
	_isRemoteActive=!_isRemoteActive;
	[_helperFunctionButton setNavBarButtonStyle:_isRemoteActive? 3 : 0];
}

- (void)initRemote
{
	_isMediaConnected = [_connection connectedToMediaServer];
	_remoteButtons = [[RemoteButtons alloc] initWithMediaConnection: _isMediaConnected];
	int totalbuttons; // = MAX([_remoteButtons getMaxRow], [_remoteButtons getMaxCol]) + 1;
	_totalPages = [_remoteButtons getTotalPages];
	
	NSLog(@"connected to media server %d", _isMediaConnected);
//	NSLog(@"totalbuttons %d totalpges %d", totalbuttons, _totalPages);
	
	int orientation = [_screenView getOrientationState];
	orientation = kOrientationVertical;
	int padding = 5;
	int butwidth, butheight;
	int xmargin = 0;
	int ymargin = 40;

	CGRect frame;
	frame.size.width = [self frame].size.width;
	frame.size.height = [self frame].size.height - kControlsBarHeight - 20;

	_remoteHolder = [[UIView alloc] initWithFrame: frame];

	frame.size.height = frame.size.width + ymargin;
	frame.origin.x = 0;
	frame.origin.y = [self frame].size.height - kControlsBarHeight - 20 - frame.size.height;
//	[self dbg: [NSString stringWithFormat: @"x:%.0f y:%.0f w:%.0f h:%.0f x:%.0f y:%.0f w:%.0f h:%.0f", [self frame].origin.x, [self frame].origin.y, [self frame].size.width, [self frame].size.height, frame.origin.x, frame.origin.y, frame.size.width, frame.size.height]];
	_remoteScroller = [[UIScroller alloc] initWithFrame: frame];
	[_remoteScroller setOpaque:YES];
	[_remoteScroller setBackgroundColor:GSColorCreateColorWithDeviceRGBA(0.0f,0.0f,0.0f, 0.98f)];

	CGRect contentFrame = frame;
	contentFrame.size.width *= _totalPages;
	[_remoteScroller setScrollHysteresis: 0];
	[_remoteScroller setShowScrollerIndicators: NO];
	[_remoteScroller setAllowsFourWayRubberBanding: NO];
	[_remoteScroller setRubberBand: 15.f forEdges: 5];
	[_remoteScroller setGridSize: frame.size];
	[_remoteScroller setContentSize: contentFrame.size];
	[_remoteScroller setDelegate: self];
	[_remoteScroller setScrollingEnabled: YES];

	_pageIndicator = [UIPageIndicator alloc];
	[_pageIndicator initWithFrame: CGRectMake(frame.size.width/2, frame.origin.y + ymargin / 2, 10, 10)];
	[_pageIndicator setPageCount: _totalPages];
	[_pageIndicator setCurrentPage: _currentPage];

//	totalbuttons = 1;

	UIPushButton *aButton;

	int h, horscrollerwidth = frame.size.width / 20;
	for (h=0; h<frame.size.width * _totalPages; h+=horscrollerwidth)
	{
		aButton = [[UIPushButton alloc] initWithImage:[UIImage imageNamed: @"horscroll.png"]];
		[aButton addTarget:self action:@selector(horScrollerPressed:) forEvents:kUIControlEventMouseDown];
		[aButton addTarget:self action:@selector(horScrollerReleased:) forEvents:(kUIControlEventMouseUpInside | kUIControlEventMouseUpOutside)];
		[aButton setFrame:CGRectMake(h,0,horscrollerwidth,ymargin)];
		[_remoteScroller addSubview:aButton];
	}

/////////////////// 111111111111111111111111111111111111111111111111
//	for (p = 0; p<_totalPages; p++)
//		for (i = 0; i<totalbuttons; i++)
//			for (j = 0; j<totalbuttons; j++)

	int i, j, p, buttonnum;
	UIImageView *iv;
	CGRect butframe;
	CGColorRef black = GSColorCreateColorWithDeviceRGBA(0,0,0,1), transparent = GSColorCreateColorWithDeviceRGBA(0,0,0,0);
	NSArray *buttons = [_remoteButtons getButtonsArray];
	NSString *whitebgfn = @"remote/whitebg.png";
	UIImage *whiteImg = [UIImage imageNamed: whitebgfn];
	for (buttonnum=0; buttonnum < [buttons count]; buttonnum++)
	{
		RemoteButton *rb = (RemoteButton*)[buttons objectAtIndex: buttonnum];
		if (rb == nil)
			continue;
		p = [rb getPage];
		i = [rb getRow];
		j = [rb getCol];
	
		butwidth = frame.size.width / [_remoteButtons getTotalColsInPage: p] - padding;
		butheight = (frame.size.height - ymargin ) / [_remoteButtons getTotalRowsInPage: p] - padding;

		butframe = CGRectMake(p * (frame.size.width + 1) + xmargin + j * (butwidth + padding), ymargin + i * (butheight + padding), butwidth, butheight);

		int maxrowcols = MAX([_remoteButtons getTotalColsInPage: p], [_remoteButtons getTotalRowsInPage: p]);
		GSFontRef font = GSFontCreateWithName("Verdana", 0, 30 - maxrowcols * 2);
	
//		NSLog(@"image: %@ %d", [rb getImage], [[rb getImage] isEqualToString: whitebgfn]);
		UIImageView *img = [[UIImageView alloc] initWithImage: [[rb getImage] isEqualToString: whitebgfn] ? whiteImg : [UIImage imageNamed: [rb getImage]]];
		[img setFrame:butframe];
		[_remoteScroller addSubview: img];

		if ([rb getImageType] != kSpecial)
		{
			UITextLabel *text = [[UITextLabel alloc] initWithFrame: butframe];
			[text setFont: font];
			[text setText: [rb getTitle]];
//			butframe.origin.x += butwidth/2  - [text frame].size.width/2;
//			butframe.origin.y += butheight/2 - [text frame].size.height/2; // 0 since it's lower case
//			butframe.size = [text frame].size;
			[text setColor:black];
			[text setBackgroundColor:transparent];
			[text setWrapsText: YES];
			[text setCentersHorizontally: YES];
			[_remoteScroller addSubview: text];
		}

		aButton = [[UIPushButton alloc] initWithFrame: butframe];
//		[aButton setDrawsShadow:YES];
		[aButton setShowPressFeedback:YES];
		[aButton addTarget:self action:@selector(remoteButtonPressed:) forEvents:kUIControlEventMouseDown];
		[aButton addTarget:self action:@selector(remoteButtonReleased:) forEvents:(kUIControlEventMouseUpInside | kUIControlEventMouseUpOutside)];
		[_remoteScroller addSubview:aButton];
		[rb setControl: aButton];		
	}
	[_remoteScroller setOffset:CGPointMake(frame.size.width * _currentPage, 0)];
	[_remoteHolder addSubview: _remoteScroller];
	[_remoteScroller setBackgroundColor:GSColorCreateColorWithDeviceRGBA(0,0,0, 0)];
	[_remoteHolder setBackgroundColor:GSColorCreateColorWithDeviceRGBA(0,0,0, 1)];
//	[[NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(showremote:) userInfo:nil repeats:NO] retain];
}

-(void)showremote:(NSTimer*)t
{
	[_scroller addSubview:_remoteHolder];
}

-(void)horScrollerPressed:(id)sender
{
	NSLog(@"horscroller pressed %@", sender);
	[_remoteScroller setScrollingEnabled:YES];
}

-(void)horScrollerReleased:(id)sender
{
	NSLog(@"horscroller released %@", sender);
//	[_remoteScroller setScrollingEnabled:NO];
}

- (void)hidePageIndicator:(NSTimer *)timerInfo
{
	[_pageIndicator removeFromSuperview];
}

- (void) scrollerDidScroll: (id) sender
{
	if (sender == _remoteScroller)
	{
		NSLog(@"scrollerdidscroll %@", sender);
		[self stopSendingRemoteControlKeys];
		[_remoteHolder addSubview: _pageIndicator];
		if (_hidePageIndicatorTimer)
		{
			[_hidePageIndicatorTimer invalidate];
			[_hidePageIndicatorTimer release];
			_hidePageIndicatorTimer = nil;
		}
		_hidePageIndicatorTimer = [[NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(hidePageIndicator:) userInfo:nil repeats:NO] retain];
		
		CGPoint pt = [_remoteScroller offset];

		// calculate a indicator for the page we are on
		// use +50 for some hysteresis on the edges
		// then divide by grid size and truncate
		int pagewidth = [_remoteScroller frame].size.width;
		if (pagewidth > 0)
		{
			int index = (int)((pt.x + pagewidth / 2) / pagewidth);
			[_pageIndicator setCurrentPage: index];
			_currentPage = index;
	//	[self dbg: [NSString stringWithFormat: @"currentpage %d", _currentPage]];
	//	NSLog(@"scroll..x=%f index=%d width=%.0f pagewidth=%d", pt.x, index, [_remoteScroller frame].size.width, pagewidth);
		}
	}
}

- (void)toggleFitWidthHeight:(id)sender
{
	UIPushButton *pButton = (UIPushButton *)sender;	
	scaleSpecialTypes wScaleState = [self getScaleState], wScaleThisButton;

	if (sender == _fitWidthButton)
		wScaleThisButton = kScaleFitWidth;
	else if (sender == _fitHeightButton)
		wScaleThisButton = kScaleFitHeight;
	else if (sender == _fitWholeButton)
		wScaleThisButton = kScaleFitWidth | kScaleFitHeight;
	else if (sender == _fitNoneButton)
		wScaleThisButton = 0;
	[self setScaleState: wScaleThisButton];
	[self setOrientation: [self getOrientationState] bForce:true];
	if (sender != _fitNoneButton)
		[_scroller scrollPointVisibleAtTopLeft: CGPointMake(0,0)];
	NSLog(@"Got Event or Scale Change");
}


- (CGRect)scrollerFrame
{
	return [_scroller frame];
}

//! The toggle keyboard button has been pressed. This method assumes
//! the controls bar is visible.
- (void)toggleKeyboard:(id)sender
{
//	NSLog(@"toggling keyboard: old=%d", (int)_isKeyboardVisible);
	
	CGRect frame = [_scroller frame];
	
	if (_keyboardView == nil)
		_keyboardView = [UIKeyboardImpl sharedInstance];
	
	if (_isKeyboardVisible)
	{
		// Remove the keyboard view.
		[_keyboardView removeFromSuperview];
		[_keyTextLabel removeFromSuperview];
		[_keyTextLabel release];
		_keyTextLabel = nil;
		
		// Adjust scroller frame back to normal size (minus the controls bar).
		frame.size.height -= kControlsBarHeight;
//		[_scroller setFrame:frame];
	}
	else
	{
		if (_isRemoteActive)
			[self toggleRemote: nil];

//		frame.size.height -= kControlsBarHeight;

		int keywidth;
		if ([self getOrientationState] != kOrientationVertical) 
		{
			CGSize ksize = CGSizeMake(480, 180);
			[_keyboardView setSize:ksize];
			[_keyboardView setOrigin:CGPointMake(0, frame.size.height - ksize.height)];
			[_keyboardView showLayout:[UIKeyboardLayoutQWERTYLandscape class]];
		}
		else
		{
			CGSize ksize = CGSizeMake(320, 216);
			[_keyboardView setSize:ksize];
			[_keyboardView setOrigin:CGPointMake(0, frame.size.height + 20 - ksize.height)];
//			[self dbg: [NSString stringWithFormat: @"boundsheight %.0f %.0f %.0f %@", frame.size.height, ksize.height, frame.size.height - ksize.height, ([self getOrientationState] == kOrientationVertical) ? @"Vertical" : @"Horizontal"]];
			[_keyboardView showLayout:[UIKeyboardLayoutQWERTY class]];
		}

		// Adjust scroller frame so that its height is from below the system
		// status bar to the top of the keyboard.
		frame = [self bounds];
		frame.size.height = frame.size.height - kControlsBarHeight - [_keyboardView frame].size.height;
//		[_scroller setFrame:frame];

		_keyTextLabel = [[UITextLabel alloc] initWithFrame:frame];
		[_keyTextLabel setFont:GSFontCreateWithName("Verdana", 0, 16.0f)];
		[_keyTextLabel setBackgroundColor:GSColorCreateColorWithDeviceRGBA(0,0,0, 0.6f)];
		[_keyTextLabel setColor:GSColorCreateColorWithDeviceRGBA(1,1,1,1)];
		[_keyTextLabel setCentersHorizontally: NO];
		[_keyTextLabel setWrapsText: YES];
		[_keyTextLabel setEllipsisStyle: kUITextLabelEllipsisLeading];
		[self addSubview:_keyTextLabel];
		_keyText = @"";

		
		// Add in the keyboard view.
		[self addSubview:_keyboardView];
//		[_keyboardView activate];
		
		// Set the delegate now that we have an active keyboard.
		[[UIKeyboardImpl activeInstance] setDelegate:self];
	}
	
	_isKeyboardVisible = !_isKeyboardVisible;
	[_keyboardButton setNavBarButtonStyle:_isKeyboardVisible? 3 : 0];
}

- (void)closing
{
	if (_isRemoteActive)
		[self toggleRemote: nil];
	if (_isKeyboardVisible)
		[self toggleKeyboard:nil];
	[self setOrientation: kOrientationVertical bForce:YES];
}

//! This message is received when the user has pressed the close connection
//! button.
- (void)closeConnection:(id)sender
{
	// Hide the keyboard before closing.
	if (_isKeyboardVisible)
	{
		[self toggleKeyboard:nil];
	}
	
	if (_delegate && [_delegate respondsToSelector:@selector(closeConnection)])
	{
		[_delegate closeConnection];
	}
}


- (void)getHelp:(id)sender
{
	[self setOrientation: kOrientationVertical bForce:YES];
	[_delegate showWebPage:@"http://direct.touchpadpro.com/4.0/controls.html" withTitle:NSLocalizedString(@"Help",nil) fromView:self];
	_browsingHelp = true;
}

- (void) alertSheet:(id)sheet buttonClicked:(int)button
{
	[sheet dismissAnimated:YES];
//	[sheet release];
}

//! Handle the right mouse button being pressed.
//!
- (void)toggleRightMouse:(id)sender
{
//	bool useRight = ![_scroller useRightMouse];
//	[_rightMouseButton setNavBarButtonStyle:useRight ? 3 : 0];
//	[_scroller setUseRightMouse:useRight];
}

//! Handle one of the modifier key buttons being pressed.
//!
- (void)toggleModifierKey:(id)sender
{
	unsigned int modifier;
	if (sender == _shiftButton)
	{
		modifier = NSShiftKeyMask;
	}
	else if (sender == _commandButton)
	{
		modifier = NSCommandKeyMask;
	}
	else if (sender == _optionButton)
	{
		modifier = NSAlternateKeyMask;
	}
	else if (sender == _controlButton)
	{
		modifier = NSControlKeyMask;
	}
	else
	{
		// Unexpected sender.
		NSLog(@"Unexpected sender = %@", sender);
		return;
	}

	// Determine the new modifier mask.
	//! @todo This logic should be in EventFilter, not here.
	unsigned int currentModifiers = [_filter pressedModifiers];
	unsigned int newModifiers = currentModifiers ^ modifier;
	bool isPressed = newModifiers & modifier;
	
	NSLog(@"current=%x, new=%x, is=%d", currentModifiers, newModifiers, (int)isPressed);
	
	// Change the button color.
	UIView *glow = (UIView *)[[sender subviews] objectAtIndex: 0];
	if (_modDoubleTap == sender)
	{
		[sender setNavBarButtonStyle: 3];
		if ([glow alpha] > 0.1f)
		{
			[glow setAlpha: 0.0f];
			return;
		}
		else
			[glow setAlpha: 0.0f];
	}
	else
	{
		[sender setNavBarButtonStyle: 0];
		[glow setAlpha: isPressed ? 1.0f : 0.0f];
	}
	_modDoubleTap = sender;
	[[NSTimer scheduledTimerWithTimeInterval:.4 target:self selector:@selector(handleModDoubleTapTimer:) userInfo:nil repeats:NO] retain];
	
	// Queue the modifier changed event.
//	if (modifier == NSAlternateKeyMask)
//		[_scroller toggleAcceleration];
	[_filter flagsChanged:newModifiers];
}

- (void) handleModDoubleTapTimer: (id) sender
{
	_modDoubleTap = nil;
}

- (void) cancelGlowingModifiers
{
	int i;
	NSArray *buttons = [_controlsView subviews];
	for (i=0; i< [buttons count]; i++)
	{
		UIView *button = (UIView*)[buttons objectAtIndex: i];
		if (button == _shiftButton || button == _controlButton || button == _commandButton || button == _optionButton)
			if ([(UIView *)[[button subviews] objectAtIndex: 0] alpha] > 0.1f)
				[self toggleModifierKey: button];
	}
}

//! Returns whether the first frame update has been received from the server.
//!
- (bool)isFirstDisplay
{
	return _isFirstDisplay;
}

-(bool)registered
{
//	NSLog(@"ARE Ve registered???????????? %d", [_delegate registered]);
	return [_delegate registered];
}

- (id)delegate
{
	return _delegate;
}

- (void)setDelegate:(id)theDelegate
{
	_delegate = theDelegate;
}

- (RFBConnection *)connection;
{
	return _connection;
}

-(void)toggleViewOnly
{
	[_scroller toggleViewOnly];
}
//! This method is invoked before the VNCView is displayed to the user, so
//! that the controls on the controls bar can be properly enabled or disabled
//! based on their relevance if view only mode is enabled. For instance,
//! the keyboard and right mouse buttons should be disabled in view only mode
//! because the user cannot type or click remotely.
- (void)enableControlsForViewOnly:(bool)isViewOnly
{
	bool notViewOnly = !isViewOnly;

	if (isViewOnly)
		{
		[_keyboardButton removeFromSuperview];
		[_shiftButton removeFromSuperview];
		[_commandButton removeFromSuperview];
		[_optionButton removeFromSuperview];
		[_controlButton removeFromSuperview];
		[_rightMouseButton removeFromSuperview];
		[_delegate setStatusBarMode: kUIStatusBarBlack duration:0];
		}
	else
		{
		[_controlsView addSubview: _keyboardButton];
		[_controlsView addSubview: _shiftButton];
		[_controlsView addSubview: _commandButton];
		[_controlsView addSubview: _optionButton];
		[_controlsView addSubview: _controlButton];
		[_controlsView addSubview: _rightMouseButton];
		[_delegate setStatusBarMode: kUIStatusBarWhite duration:0];
		}
/*	
	[_keyboardButton setEnabled:notViewOnly];
	[_shiftButton setEnabled:notViewOnly];
	[_commandButton setEnabled:notViewOnly];
	[_optionButton setEnabled:notViewOnly];
	[_controlButton setEnabled:notViewOnly];
	[_rightMouseButton setEnabled:notViewOnly];
*/
	
}

//! The frame buffer has been created by the connection object and is
//! being passed to us. We pass it along to the underlying content view
//! that does the actual drawing.
- (void)setFrameBuffer:(id)aBuffer;
{
	[_screenView setFrameBuffer:aBuffer];
}

//! Either a new connection is being set or the connection is being cleared
//! because it was closed. When a new connection is being set, we hook up
//! some objects to each other, such as the EventFilter.
- (void)setConnection:(RFBConnection *)connection
{
    _connection = connection;
	if (_connection)
	{
		_isFirstDisplay = false;
		_showedTMSerror = false;
		[self initControlsBar];
		_filter = [_connection eventFilter];
		[_filter setView:_scroller];
		[_scroller setEventFilter:_filter];
		[_scroller setViewOnly:[_connection viewOnly]];
		[_scroller scrollPointVisibleAtTopLeft:CGPointMake(0, 0)];
		[_screenView setNeedsDisplay];
		
		// Enable or disable controls depending on view only mode.
		[self enableControlsForViewOnly:[_connection viewOnly]];
	}
	else
	{
		if (_filter != nil)
		{
//			NSLog(@"CLOSING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
			// The connection was closed.
			_filter = nil;
			[_scroller setEventFilter:nil];
			[_scroller cleanUpMouseTracks];
			[_screenView setFrameBuffer:nil];
			[_screenView setOrientationState:0];
			// Get the screen view to redraw itself in black.
//			[_screenView setNeedsDisplay];
		}
	}
}

- (UIHardwareOrientation)getOrientationState;
{
	return [_screenView getOrientationState];
}


- (scaleSpecialTypes)getScaleState
{
	return _scaleState;
}

- (void)setScaleState:(scaleSpecialTypes)wScaleState
{
	_scaleState = wScaleState;
}

- (float)scaleFitCurrentScreen: (scaleSpecialTypes) wScaleState
{
		float dx,dy, wScaleX, wScaleY, wScale = 10;
		
		NSLog(@"In scale fit");
		switch ([self getOrientationState])
		{
			case kOrientationVerticalUpsideDown:
			case kOrientationVertical:
				dx = _ipodScreenSize.width;
				dy = _ipodScreenSize.height;
				break;
				
			default:
			case kOrientationHorizontalLeft:
			case kOrientationHorizontalRight:
				dx = _ipodScreenSize.height;
				dy = _ipodScreenSize.width;
				break;
		}
		
		wScaleX = dx / _vncScreenSize.width;
		wScaleY = dy / _vncScreenSize.height;
		switch (wScaleState)
		{
			case kScaleFitWhole:  // fit Whole Screen on IPod
				wScale = wScaleX < wScaleY ? wScaleX : wScaleY;
				break;

			case kScaleFitWidth:  // fit Width
				wScale = wScaleX;
				break;

			case kScaleFitHeight: // fit Height
				wScale = wScaleY;
                break;
		}
	NSLog(@"Out scale fit");
	return wScale;
}

- (void)setScalePercent:(float)wScale
{
	if (_scaleState != kScaleFitNone)
    {
		wScale = [self scaleFitCurrentScreen: _scaleState];
	}
//	NSLog(@"New Scale = %f", wScale);
	[_screenView setScalePercent: wScale];
}

- (CGRect)getFrame
{
	return [_screenView getFrame];
}

- (float)getScalePercent
{
	return [_screenView getScalePercent];
}

- (CGPoint)getIPodScreenPoint:(CGRect)r bounds:(CGRect)bounds
{
	return [_screenView getIPodScreenPoint: r bounds:bounds];
}

- (void)finishedBrowsingHelp
{
	_browsingHelp = false;
}

- (void)setOrientation:(UIHardwareOrientation)wOrientation bForce:(int)bForce
{
	CGRect jframe = [_scroller frame];
	CGSize vncScreenSize = _vncScreenSize;
	CGSize newRemoteSize;

	if ([_scroller acceleration] || !_connection || _browsingHelp)
		return;

	if(!(wOrientation == kOrientationVertical // || wOrientation == kOrientationVerticalUpsideDown 
		|| wOrientation == kOrientationHorizontalLeft || wOrientation == kOrientationHorizontalRight))
	{
		return;
	}

	if (![[VNCPreferences sharedPreferences] allowRotation] && wOrientation != kOrientationVertical)
		return;

//	[_delegate setStatusBarMode:kUIStatusBarWhite orientation:wOrientation==kOrientationVertical?0:wOrientation==kOrientationHorizontalLeft?90:-90 duration:0.1f];

	if (wOrientation == kOrientationVertical)
		[_delegate setStatusBarMode:kUIStatusBarWhite orientation:0 duration:0.1f];
	else
		[_delegate setStatusBarMode:kUIStatusBarNone orientation:0 duration:0.1f];

	NSLog(@"VNC Screen Size  = %f %f", vncScreenSize.width, vncScreenSize.height);
	if (bForce || (_connection && wOrientation != [_screenView getOrientationState]))
	{
		UIHardwareOrientation oldOrientation = [_screenView getOrientationState];
//		NSLog(@"Orientation Change %d", wOrientation);

		[_screenView setOrientationState:wOrientation];
	
		if (wOrientation == kOrientationVertical || wOrientation == kOrientationVerticalUpsideDown)
		{
			newRemoteSize = vncScreenSize;
			if (!bForce)
				{
				if (oldOrientation == kOrientationHorizontalLeft || oldOrientation == kOrientationHorizontalRight)
					[self showControls: _savedControlShowState];
				}
		}
		else
		{
			newRemoteSize.width = vncScreenSize.height;
			newRemoteSize.height = vncScreenSize.width;
			if (!bForce)
				{
				_savedControlShowState = _areControlsVisible;
				[self showControls:0];
				}
		}

//		CGRect frame = [_controlsView frame];
//		frame.origin.y += kControlsBarHeight;
//		[_controlsView setFrame:frame];
		bool activateRemote=NO;
		if (_isRemoteActive)
		{
			[self toggleRemote: nil];
			activateRemote=YES;
		}
		CGRect changeself;
//		[_screenView setBackgroundColor:GSColorCreateColorWithDeviceRGBA(1,1,1, 1)];
//		[_scroller setBackgroundColor:GSColorCreateColorWithDeviceRGBA(0,1,0, 0.5)];
//		[self setBackgroundColor:GSColorCreateColorWithDeviceRGBA(0,255,0, 0.5)];

		CGRect oldscrollerframe = [_mainView frame];
		CGRect oldscrollerbounds = [_mainView bounds];
		CGRect oldselfframe = [self frame];
		CGRect oldselfbounds = [self bounds];
		float sbheight = [UIHardware statusBarHeight];
		CGRect futureframe = CGRectMake(
						wOrientation==kOrientationVertical?0.0f:0.0f,
						wOrientation==kOrientationVertical?0.0f:0.0f,
						wOrientation==kOrientationVertical?[UIHardware mainScreenSize].width:[UIHardware mainScreenSize].height,
						wOrientation==kOrientationVertical?[UIHardware mainScreenSize].height:[UIHardware mainScreenSize].width);
	[_delegate setUIOrientation: wOrientation];
	CGRect screenframe = CGRectMake(0.0f, 0.0f, [UIHardware mainScreenSize].width, [UIHardware mainScreenSize].height);
	CGRect mainframe   = CGRectMake(0.0f, 0.0f, [UIHardware mainScreenSize].width, [UIHardware mainScreenSize].height);
	if (wOrientation==kOrientationVertical)
	{
		//screenframe = [UIHardware fullScreenApplicationContentRect];
//		screenframe.origin.y = sbheight;
//		screenframe.size.height -=sbheight;
//		mainframe.size.height-=sbheight;
	}
	else 
	{
//		screenframe.size.width -=sbheight;
//		mainframe.size.width -=sbheight;
//		if (wOrientation==kOrientationHorizontalRight)
//			screenframe.origin.x = sbheight;
	}	
	bool keyboardWasVisible = false;

	[UIView beginAnimations:nil];
	[UIView setAnimationDuration:0.1f];

	NSString *savedtext;
	if (_isKeyboardVisible)
	{
		savedtext = [NSString stringWithFormat: @"%@", _keyText];
		[self toggleKeyboard:nil];
		keyboardWasVisible = YES;
	}

		[self setBounds: futureframe];
		[self rotateToDegrees: wOrientation==kOrientationVertical?0:wOrientation==kOrientationHorizontalLeft?90:-90];
		[_window setFrame:screenframe];
		[_mainView setFrame: mainframe];

		CGRect controlsframe = [self bounds];
		controlsframe.origin.y = controlsframe.size.height - kControlsBarHeight;
		controlsframe.size.height = kControlsBarHeight;
		[_controlsView setFrame: controlsframe];
		if (oldOrientation == kOrientationVertical && wOrientation != kOrientationVertical && !_isStretched)
		{
			[self stretch:_keyboardButton big:YES];
			[self stretch:_exitButton big:YES];
			[self stretch:_shiftButton big:YES];
			[self stretch:_commandButton big:YES];
			[self stretch:_optionButton big:YES];
			[self stretch:_controlButton big:YES];
			[self stretch:_helperFunctionButton big:YES];
			[self stretch:_rightMouseButton big:YES];
			_isStretched = YES;
		}
		else if (wOrientation == kOrientationVertical && _isStretched)
		{
			[self stretch:_keyboardButton big:NO];
			[self stretch:_exitButton big:NO];
			[self stretch:_shiftButton big:NO];
			[self stretch:_commandButton big:NO];
			[self stretch:_optionButton big:NO];
			[self stretch:_controlButton big:NO];
			[self stretch:_helperFunctionButton big:NO];
			[self stretch:_rightMouseButton big:NO];
			_isStretched = NO;
		}
		
		

		CGRect scrollerframe = [self bounds];
		scrollerframe.size.height-=kControlsBarHeight;
		scrollerframe.origin.x=0;
		if (wOrientation==kOrientationVertical)
		{
			scrollerframe.size.height-=20;
			scrollerframe.origin.y=20;
		}
		else
			scrollerframe.origin.y=0;		
		[_scroller setFrame: scrollerframe];
		scrollerframe = [_scroller frame];
//		[self scrollToLastMousePoint];
		[[NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:@selector(scrollToLastMousePointTimer:) userInfo:nil repeats:NO] retain];
//		[self dbg: [NSString stringWithFormat: @"%.0f,%.0f,%.0f,%.0f %.0f,%.0f,%.0f,%.0f %.0f,%.0f", jframe.origin.x, jframe.origin.y, jframe.size.width, jframe.size.height,   scrollerframe.origin.x, scrollerframe.origin.y, scrollerframe.size.width, scrollerframe.size.height, [_scroller offset].x, [_scroller offset].y]];

	if (keyboardWasVisible)
	{
		[self toggleKeyboard:nil];
		_keyText = [NSString stringWithFormat: @"%@", savedtext];
		[self showTypedText];
	}

	//remote rotation
	{
		float scale = wOrientation == kOrientationVertical ? 1 : ([self frame].size.width - kControlsBarHeight) / ([self frame].size.height - kControlsBarHeight - 20) ;
//		[self dbg: [NSString stringWithFormat: @"scale:%f", scale]];
		[_remoteHolder setTransform: CGAffineTransformMakeScale(scale, scale)];

		CGRect remoteframe = [_remoteHolder frame];
		remoteframe.size.height = (wOrientation == kOrientationVertical ? [self frame].size.height : [self frame].size.width) - kControlsBarHeight - (wOrientation == kOrientationVertical ? 20 : 0);
		remoteframe.origin.x = (wOrientation == kOrientationHorizontalLeft ? [self frame].size.height - remoteframe.size.width : 0 );
		remoteframe.origin.y = (wOrientation == kOrientationVertical ? 20 : 0);//(wOrientation == kOrientationVertical ? [self frame].size.height - kControlsBarHeight - remoteframe.size.height : 0 ); 
		[_remoteHolder setFrame: remoteframe];
//		[self dbg: [NSString stringWithFormat: @"(%3.0f%,%3.0f%)(%3.0f%,%3.0f%)", remoteframe.origin.x, remoteframe.origin.y, remoteframe.size.width, remoteframe.size.height]];
	}

	[UIView endAnimations];



		CGRect newscrollerframe = [_mainView frame];
		CGRect newscrollerbounds = [_mainView bounds];
		CGRect newselfframe = [self frame];
		CGRect newselfbounds = [self bounds];
	if (NO)
			[self dbg: [NSString stringWithFormat: @"scrof(%.0f%,%.0f%)(%.0f%,%.0f%), scrob(%.0f%,%.0f%),(%.0f%,%.0f%), scrnf(%.0f%,%.0f%),(%.0f%,%.0f%), scrnb(%.0f%,%.0f%),(%.0f%,%.0f%), selof(%.0f%,%.0f%)(%.0f%,%.0f%), selob(%.0f%,%.0f%),(%.0f%,%.0f%), selnf(%.0f%,%.0f%),(%.0f%,%.0f%), selnb(%.0f%,%.0f%),(%.0f%,%.0f%)", 
			oldscrollerframe.origin.x, oldscrollerframe.origin.y, oldscrollerframe.size.width, oldscrollerframe.size.height, 
			oldscrollerbounds.origin.x, oldscrollerbounds.origin.y, oldscrollerbounds.size.width, oldscrollerbounds.size.height, 
			newscrollerframe.origin.x, newscrollerframe.origin.y, newscrollerframe.size.width, newscrollerframe.size.height, 
			newscrollerbounds.origin.x, newscrollerbounds.origin.y, newscrollerbounds.size.width, newscrollerbounds.size.height,
			oldselfframe.origin.x, oldselfframe.origin.y, oldselfframe.size.width, oldselfframe.size.height, 
			oldselfbounds.origin.x, oldselfbounds.origin.y, oldselfbounds.size.width, oldselfbounds.size.height, 
			newselfframe.origin.x, newselfframe.origin.y, newselfframe.size.width, newselfframe.size.height, 
			newselfbounds.origin.x, newselfbounds.origin.y, newselfbounds.size.width, newselfbounds.size.height
			]];

//		[self dbg: [NSString stringWithFormat: @"oframe(%3.0f%,%3.0f%)(%3.0f%,%3.0f%), obound(%3.0f%,%3.0f%),(%3.0f%,%3.0f%), nframe(%3.0f%,%3.0f%),(%3.0f%,%3.0f%), nbound(%3.0f%,%3.0f%),(%3.0f%,%3.0f%)", oldframe.size.width, oldframe.size.height, oldbounds.size.width, oldbounds.size.height, newframe.size.width, newframe.size.height, newbounds.size.width, newbounds.size.height]];

//		[self updateControls];
		if (activateRemote)
		{
			[self toggleRemote: nil];
		}

		if ([self getScaleState] != kScaleFitNone)
		{
			[self setScalePercent: 1];
		}
		float fUnscale = [_screenView getScalePercent];

//		CGRect bounds = CGRectMake(0, 0, vncScreenSize.width, vncScreenSize.height);
//		[_screenView setBounds: bounds];
//		CGRect contentframe = [_screenView frame];
//		contentframe.origin.y = wOrientation==kOrientationVertical ? 20 : 0;
//		[_screenView setFrame: contentframe];

		CGAffineTransform matrix = CGAffineTransformRotate(CGAffineTransformMakeScale(0 - fUnscale, fUnscale), 
				([_screenView getOrientationDeg])  * M_PI / 180.0f);
		[_filter setBackToVNCTransform: CGAffineTransformInvert(matrix)];
		[_filter setOrientation: wOrientation];

//		newRemoteSize.width = newRemoteSize.width * [_screenView getScalePercent];
//		newRemoteSize.height = newRemoteSize.height  * [_screenView getScalePercent];

//		NSLog(@"newremotesize width=%.0f, height=%.0f", newRemoteSize.width, newRemoteSize.height);

//		CGRect newframe = [_scroller frame];
//		CGRect newbounds = [_scroller bounds];
//		[self dbg: [NSString stringWithFormat: @"%3.0f%,%3.0f%,%3.0f%,%3.0f%, %3.0f%,%3.0f%,%3.0f%,%3.0f%", oldframe.size.width, oldframe.size.height, oldbounds.size.width, oldbounds.size.height, newframe.size.width, newframe.size.height, newbounds.size.width, newbounds.size.height]];

//		NSLog(@"New Screen View = %f %f", newRemoteSize.width, newRemoteSize.height);
//		Animate if special double click zoom
//		[_screenView setRemoteDisplaySize:newRemoteSize animate:bForce == 2 ? YES : !bForce];
	
		// Reset our scroller's content size.
//		[_scroller setContentSize:newRemoteSize];
	}
}

- (void)scrollToLastMousePointTimer:(id) blah
{
	[self scrollToLastMousePoint];
}

- (void)scrollToLastMousePoint
{
	if (_cursor)
	{
		int o = [self getOrientationState];
		bool v = o==kOrientationVertical;
		CGPoint p = _lastMousePoint;
//		_displayRect = CGRectMake(0,0,[_connection displaySize].width, [_connection displaySize].height); 
		_serverRect = CGRectMake(_serverOffset.x, _serverOffset.y, _vncScreenSize.width, _vncScreenSize.height);
//		_clientRect = CGRectMake(_clientOffset.x, _clientOffset.y, v?320:480, (v?460:320) - kControlsBarHeight);

//		NSLog(@"1CGRect does %@ contain p", (CGRectContainsPoint(_serverRect, p)? @"" : @"not"));

		if (!CGRectContainsPoint(_serverRect, p))
		{
			while (p.x < _serverOffset.x) _serverOffset.x -= _serverRect.size.width;
			while (p.x > _serverOffset.x + _serverRect.size.width) _serverOffset.x += _serverRect.size.width;
			while (p.y < _serverOffset.y) _serverOffset.y -= _serverRect.size.height;
			while (p.y > _serverOffset.y + _serverRect.size.height) _serverOffset.y += _serverRect.size.height;
			
			CGRect reqRect = [_screenView bounds];
			reqRect.origin = _serverOffset;
			if (CGRectGetMaxY(reqRect) > [_connection displaySize].height)
				reqRect.size.height = [_connection displaySize].height - reqRect.origin.y;
			[_screenView displayFromBuffer:reqRect serverOffset:_serverOffset];
		}		
		
//		NSLog(@"serverOffset %.0f,%.0f", _serverOffset.x, _serverOffset.y);
		
		// p is a point on displayRect, but we need to translate it ourselves		
		
		p.x -= _serverOffset.x;
		p.y -= _serverOffset.y;
		p.x = MAX(0, p.x - (v?160:240));
		p.x = MIN(MIN([_connection displaySize].width - _serverOffset.x, _vncScreenSize.width) - (v?320:480), p.x);
		p.y = MAX(0, p.y - (v?(480-20)/2:160) + (kControlsBarHeight/2));
		p.y = MIN(MIN([_connection displaySize].height - _serverOffset.y, _vncScreenSize.height) - (v?(480-20):320) + kControlsBarHeight, p.y);
		_clientOffset = p;
		[_scroller setOffset: _clientOffset];

		CGPoint cursorOrigin = _lastMousePoint;
		cursorOrigin.x -= _serverOffset.x;
		cursorOrigin.y -= _serverOffset.y;
		[_cursor setOrigin: cursorOrigin];
	}
//	[self dbg: [NSString stringWithFormat: @"%3.0f%,%3.0f%", p.x, p.y]];	
//	NSLog(@"vncview lmp %f,%f", p.x, p.y);
}

- (void)setLastMousePoint: (CGPoint) p
{
	_lastMousePoint = p;
	[self scrollToLastMousePoint];
}

- (void)stretch: (UINavBarButton*)pb big:(bool)b
{
	CGRect f = [pb frame];
	f.origin.x *= b ? 1.5 : 1.0/1.5;
//	f.size.width *= b ? 1.5 : 1.0/1.5;
	[pb setFrame: f];
}

- (void)setWindow: (UIWindow*)w
{
	_window = w;
}

- (void)setMainView: (UIView*)u
{
	_mainView = u;
}

- (void)setRemoteComputerName:(NSString *)name
{
	_remoteComputerName = name;
}

- (CGSize)vncScreenSize
{
	return _vncScreenSize;
}

- (void)setRemoteDisplaySize:(CGSize)remoteSize
{
	NSLog(@"#1 Setting VNC screen size %f %f", remoteSize.width, remoteSize.height);

	if ([(NSArray *)[_cursor subviews] count] > 0)
	{
		id obj = [(NSArray *)[_cursor subviews] objectAtIndex: 0];
		if (obj != nil)
		{
			[(UIImageView*)obj removeFromSuperview];
			[(UIImageView*)obj release];
		}
	}
	if (_cursor != nil)
	{
		if ([_cursor superview] != nil)
		{
			[_cursor removeFromSuperview];
			[_cursor release];
			_cursor = nil;
		}
	}
	
	if ([_connection viewOn])
	{
		UIImageView *cursorView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:([_connection macMode] ? @"cursormac.png" : @"cursorwin.png")]];
		CGRect cursorframe = [cursorView frame];
		_cursor = [[UIView alloc] initWithFrame: cursorframe];
		cursorframe.origin.x -= [_connection macMode] ? 1 : 0;
		cursorframe.origin.y -= [_connection macMode] ? 2 : 3;
		[cursorView setFrame: cursorframe];
		[cursorView setAlpha: 1];
		[_cursor addSubview: cursorView];
		[_scroller addSubview: _cursor];
	}

	// ******************************************************************************
	// BAD BAD BAD IPHONE BUG WITH DEVICE CONTEXT ONLY ABLE to reach 1024 then crash 
	// ******************************************************************************
//	if ([_connection macMode])
//		_vncScreenSize = CGSizeMake(remoteSize.width, MIN(((2*1024*1024) / remoteSize.width), remoteSize.height));
//	else
//		_vncScreenSize = CGSizeMake(1,1);
//	_vncScreenSize = CGSizeMake(320, 480);
	_vncScreenSize = CGSizeMake(remoteSize.width,remoteSize.height);
	_vncScreenSize = CGSizeMake(MIN([[VNCPreferences sharedPreferences] maxWidth],remoteSize.width), MIN([[VNCPreferences sharedPreferences] maxHeight],remoteSize.height));

	_serverOffset = CGPointMake(0,0);
	_serverRect = CGRectMake(_serverOffset.x, _serverOffset.y, _vncScreenSize.width, _vncScreenSize.height);

	[self setScaleState: kScaleFitNone];
	[self setOrientation: kOrientationVertical bForce:false];
	[_screenView setRemoteDisplaySize:_vncScreenSize animate:NO viewOn:[_connection viewOn]];
	[_scroller setContentSize:_vncScreenSize];
}

//! The connection object is telling us that a region of the framebuffer
//! needs to be redrawn.
- (void)displayFromBuffer:(CGRect)aRect
{	
	[_screenView displayFromBuffer:aRect serverOffset:_serverOffset];
	
	// If this is our first display update then Transition to the VNC server screen
	if (!_isFirstDisplay)
	{
		_isFirstDisplay = true;
		[_scroller scrollPointVisibleAtTopLeft:_ptStartupTopLeft];
		[_delegate gotFirstFullScreenTransitionNow];
		[_filter firstMouseAt];
	}
}

//! This method is supposed to draw a list of rectangles. Unfortunately, the UIKit
//! doesn't seem to have an equivalent to lockFocus/unlockFocus, so there's no way
//! to get a drawing context outside of the regular draw methods. But it seems
//! that this method isn't called much (never seen it once), so it's not a big deal.
- (void)drawRectList:(id)aList
{
	NSLog(@"VNCView:drawRectList:%@", aList);
	
	// XXX this may not be cool!
//    [self lockFocus];
//    [aList drawRectsInRect:[self bounds]];
//    [self unlockFocus];
}

- (CGRect)contentRect
{
	return _serverRect;
}

#pragma mark ** UIKeyboardInput **

- (void)deleteBackward
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	
	if ([_keyText length] > 0)
		_keyText = [_keyText substringToIndex: [_keyText length] - 1];
	[self showTypedText];
	[_filter keyTyped:@"\x007f"];
}

- (void)insertText:(id)text
{
//	NSLog(@"%s:%@", __PRETTY_FUNCTION__, text);

	char c = [text characterAtIndex: 0];
//	if (c >= '0' && c<='9' && ![_connection macMode] && [_filter pressedModifiers] & NSAlternateKeyMask)
//	{
//		[self sendFunctionKeys: [text intValue]];
//		[self clearTypedText];
//	}
//	else
	{
		if ([text characterAtIndex: 0] == '\n')
			[self clearTypedText];
		
		text = [_filter pressedModifiers] & NSShiftKeyMask ? [text uppercaseString] : text;
		
		_keyText=[NSString stringWithFormat: @"%@%@", _keyText, text];
		[self showTypedText];
		[_filter keyTyped:text];
	}
	[self cancelGlowingModifiers];
}

- (void)showTypedText
{
	int textlength = [_keyText length];
//	NSLog(@"key dbg %d", MAX(0, textlength - 5));
	[_keyTextLabel setText: _keyText];//[_keyText substringFromIndex: MAX(0, textlength - 5)]];
}

- (void)clearTypedText
{
	_keyText = @"";
	[self showTypedText];
}

- (void)replaceCurrentWordWithText:(id)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (void)setMarkedText:(id)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (id)markedText
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return nil;
}

- (unsigned short)characterInRelationToCaretSelection:(int)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return 0; //L' ';
}

- (unsigned short)characterBeforeCaretSelection
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return 0; //L' ';
}

- (unsigned short)characterAfterCaretSelection
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return 0; //L' ';
}

- (struct __GSFont *)fontForCaretSelection
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return [UIPushButton defaultFont];
}

- (struct CGColor *)textColorForCaretSelection
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return [UITextTraits defaultCaretColor];
}

- (struct CGRect)rectContainingCaretSelection
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return CGRectMake(0,0,0,0);
}

- (id)wordRangeContainingCaretSelection
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return nil;
}

- (id)wordContainingCaretSelection
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return nil;
}

- (id)wordInRange:(id)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return nil;
}

- (void)expandSelectionToStartOfWordContainingCaretSelection
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (int)wordOffsetInRange:(id)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return 0;
}

- (BOOL)spaceFollowsWordInRange:(id)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return NO;
}

- (id)previousNGrams:(unsigned int)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return nil;
}

- (struct _NSRange)selectionRange
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return NSMakeRange(0, 0);
}

- (BOOL)hasSelection
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return NO;
}

- (BOOL)selectionAtDocumentStart
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return NO;
}

- (BOOL)selectionAtSentenceStart
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return NO;
}

- (BOOL)selectionAtWordStart
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return NO;
}

- (BOOL)rangeAtSentenceStart:(id)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return NO;
}

- (void)markCurrentWordForAutoCorrection:(id)fp8 correction:(id)fp12
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (void)moveBackward:(unsigned int)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (void)moveForward:(unsigned int)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (void)selectAll
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (void)setText:(id)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (id)text
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return @"";
}

- (void)updateSelectionWithPoint:(struct CGPoint)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (void)setCaretChangeListener:(id)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (struct CGRect)caretRect
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return CGRectMake(0,0,0,0);
}

- (struct CGRect)convertCaretRect:(struct CGRect)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return CGRectMake(0,0,0,0);
}

- (id)keyboardInputView
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return self;
}

- (id)textTraits
{
	UITextTraits * traits = [UITextTraits defaultTraits];
	[traits setAutoCapsType:0];	//?
	[traits setAutoCorrectionType:0];	//?
	[traits setAutoEnablesReturnKey:NO];
	return traits;
}

- (BOOL)isShowingPlaceholder
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return NO;
}

- (void)setupPlaceholderTextIfNeeded
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (BOOL)isProxyFor:(id)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return NO;
}

- (BOOL)interceptKeyEvent:(GSEventRef)theEvent
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	
//	unsigned eventType = GSEventGetType(theEvent);
//	unsigned subType = GSEventGetSubType(theEvent);
//	
//	NSLog(@"  type=%d; subtype=%d", eventType, subType);
//	
//	switch (eventType)
//	{
//		// key down
//		case 10:
//			[_filter keyDown:theEvent];
//			break;
//		
//		// key up
//		case 11:
//			[_filter keyUp:theEvent];
//			break;
//	}
	
	return NO;
}

/*
//These Methods track delegate calls made to the application
- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector 
{
	NSLog(@"Requested method for selector: %@", NSStringFromSelector(selector));
	return [super methodSignatureForSelector:selector];
}

- (BOOL)respondsToSelector:(SEL)aSelector 
{
	NSLog(@"Request for selector: %@", NSStringFromSelector(aSelector));
	return [super respondsToSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation 
{
	NSLog(@"Called from: %@", NSStringFromSelector([anInvocation selector]));
	[super forwardInvocation:anInvocation];
}
*/
@end
